#ifndef ARSEXPRESSION_H
#define ARSEXPRESSION_H

#include <QVariant>
#include <QString>
#include <QObject>

class ARSExpr : public QObject
{
    Q_OBJECT

public:
    ARSExpr(QObject * parent = 0);

    virtual QVariant result() const = 0;
    virtual bool isNull() const = 0;
    virtual QString symbol() const = 0;
    virtual QString toString() const = 0;
};

class ARSExprParseError : public ARSExpr
{
    Q_OBJECT

public:
    ARSExprParseError(QObject * parent = 0);

    QVariant result() const;
    bool isNull() const;
    QString toString() const;
    QString symbol() const;
};

class ARSExprConst : public ARSExpr
{
    Q_OBJECT

public:
    ARSExprConst(QVariant var, QObject * parent = 0);
    void setVar(QVariant var);
    QVariant var() const;

    QVariant result() const;
    bool isNull() const;
    QString toString() const;
    QString symbol() const;

private:
    QVariant m_var;
};

class ARSExprField : public ARSExpr
{
    Q_OBJECT

public:
    enum FieldState
    {
        Regular,
        Database,
        Transaction
    };

    ARSExprField(int fieldID = -1, FieldState state = Regular, QObject * parent = 0);
    void setFieldID(int id);
    int fieldID() const;
    void setFieldState(FieldState state);
    FieldState fieldState() const;

    QVariant result() const;
    bool isNull() const;
    QString toString() const;
    QString symbol() const;

private:
    int m_fieldID;
    FieldState m_fieldState;
};

class ARSExprNot : public ARSExpr
{
    Q_OBJECT

public:
    ARSExprNot(ARSExpr * child = 0, QObject * parent = 0);
    void setChild(ARSExpr * child);
    ARSExpr * child() const;

    QVariant result() const;
    bool isNull() const;
    QString toString() const;
    QString symbol() const;

private:
    ARSExpr * m_child;
};

class ARSExprBinary : public ARSExpr
{
    Q_OBJECT

public:
    ARSExprBinary(ARSExpr * left = 0, ARSExpr * right = 0, QObject * parent = 0);
    void setLeft(ARSExpr * left);
    ARSExpr * left() const;
    void setRight(ARSExpr * right);
    ARSExpr * right() const;

    bool isNull() const;
    QString toString() const;

protected:
    ARSExpr * m_left;
    ARSExpr * m_right;
};

class ARSExprAnd : public ARSExprBinary
{
    Q_OBJECT

public:
    ARSExprAnd(ARSExpr * left = 0, ARSExpr * right = 0, QObject * parent = 0);

    QVariant result() const;
};

class ARSExprOr : public ARSExprBinary
{
    Q_OBJECT

public:
    ARSExprOr(ARSExpr * left = 0, ARSExpr * right = 0, QObject * parent = 0);

    QVariant result() const;
};

#endif // ARSEXPRESSION_H
